package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"runtime"
	"sync"
)

var str string = "string"

//用来析构变量
func CopyFile(dst, src string) (written int64, err error) {
	srcF, err := os.Open(src)
	if err != nil {
		log.Println("open file failed, err is ", err)
		return
	}
	defer srcF.Close()

	dstF, err := os.Create(dst)
	if err != nil {
		log.Println("Create file failed, err is ", err)
		return
	}
	defer dstF.Close()
	return io.Copy(dstF, srcF)
}

//defer是实时捕获和解析参数
func DeferParam() {
	i := 0
	defer func(m int) {
		log.Println(m)
	}(i)
	i++
}

func DeferNoParam() {
	i := 0
	defer func() {
		log.Println(i)
	}()
	i++
}

func DeferOrder() {
	for i := 0; i < 5; i++ {
		defer func(m int) {
			log.Println(m)
		}(i)
	}
}

func DeferReturn() (res int) {
	defer func() {
		res++
		log.Println(res)
	}()

	return 0
}

func max() {
	runtime.GOMAXPROCS(1)
	wg := sync.WaitGroup{}
	wg.Add(20)
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Println(i)
			wg.Done()
		}()
	}
	for i := 0; i < 10; i++ {
		go func(i int) {
			fmt.Println(i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

type Slice []int

func NewSlice() *Slice {
	slice := make(Slice, 0)
	return &slice
}

func (s *Slice) AddSlice(val int) *Slice {
	*s = append(*s, val)
	log.Println(val)
	return s
}

// func Funlv1() {
// 	defer func() {
// 		log.Println("Funlv1 exit ...")
// 	}()
// 	log.Println("Funlv1 begin")
// 	panic("sorry, Funlv1 panic")
// 	log.Println("Funlv1 end")
// }

// func Funlv2() {
// 	defer func() {
// 		log.Println("Funlv2 exit ...")
// 	}()
// 	log.Println("Funlv2 begin")
// 	Funlv1()
// 	log.Println("Funlv2 end")
// }

func Funlv1Safe() {
	defer func() {
		if err := recover(); err != nil {
			log.Println("Funlv1 catch panic , err is ", err)
		}
		log.Println("Funlv1 exit ...")
	}()
	log.Println("Funlv1 begin")
	panic("sorry, Funlv1 panic")
	log.Println("Funlv1 end")
	defer func() {
		log.Println("after break, defer func")
	}()
}

func Funlv2Safe() {
	defer func() {
		if err := recover(); err != nil {
			log.Println("Funlv2 catch panic , err is ", err)
		}
		log.Println("Funlv2 exit ...")
	}()
	log.Println("Funlv2 begin")
	Funlv1Safe()
	log.Println("Funlv2 end")
}

func Return() {
	if 1 == 1 {
		return
	}
	defer func() {
		log.Println("return defer invoked")
	}()
}

func defer_call() {
	defer func() { fmt.Println("打印前") }()
	defer func() { fmt.Println("打印中") }()
	defer func() { fmt.Println("打印后") }()
	panic("触发异常")
}

func calc(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func main() {
	// CopyFile("D:\\github\\gointerview\\defer\\dst.txt", "D:\\github\\gointerview\\defer\\src.txt")
	// DeferParam()
	// DeferNoParam()
	// DeferOrder()
	// DeferReturn()
	// max()

	// s := NewSlice()
	// defer s.AddSlice(1).AddSlice(3)
	// s.AddSlice(2)
	// Funlv2()
	//Funlv2Safe()
	//defer_call()
	a := 1
	b := 2
	defer calc("1", a, calc("10", a, b))
	defer calc("2", a, calc("20", a, b))
}
